﻿using System;
using System.Globalization;
using System.Text;

namespace calendar_generator
{
	public class Binominal
	{
		#region Fields
		// Start of sexagenary cycles
		//private int _startYear = 1864;	//Milestone 'Jia Zi' year
		private DateTime _startDate =
			new DateTime(1899, 12, 22);		//Milestone 'Jia Zi' day
		private string[] stemBgNames = new string[] { "дзя", "и", "бин", "дин", "у", "дзи", "гън", "син", "жън", "гуей" };
		private string[] branchBgNames = new string[] { "дзъ", "чоу", "ин", "мао", "чън", "съ", "у", "вей", "шън", "юй", "сю", "хай" };

		private string[] stemBgAbrs = new string[] { "", "+Д", "-д", "+О", "-о", "+З", "-з", "+М", "-м", "+В", "-в" };
		private string[] branchBgAbrs = new string[] { "", "+В", "-з", "+Д", "-д", "+З", "-о", "+О", "-z", "+М", "-м", "+Z", "-в" };
		#endregion Fields

		#region Properties
		public DateTime ForDate { get; private set; }
		public sbyte Id { get; private set; }
		public Stems Stem { get; private set; }
		public Branches Branch { get; private set; }
		public string Code
		{
			get
			{
				return ((int)Stem).ToString("00") +
						"-" + ((int)Branch).ToString("00");
			}
		}

		public string BgName { get { return GetBgName(); } }
		public string BgAbr { get { return GetBgAbr(); } }

		public string TdTriad
		{
			get
			{
				StringBuilder ret = new StringBuilder();

				ret.Append("<td>");
				ret.Append(ForDate.ToString("ddd", new CultureInfo("bg-BG")).Substring(0, 2));
				ret.Append("</td><td>#</td><td>");
				ret.Append(GetBgName());
				ret.Append("</td>");

				return ret.ToString();
			}
		}
		#endregion Properties

		#region ctors
		public Binominal(DateTime date)
		{
			this.ForDate = date;

			// Calculate days difference
			TimeSpan span = date.Subtract(this._startDate);
			int diff = (int)span.TotalDays;
			
			// Try to init binominal data
			diff = GetSexagesimalIndex(diff);
			TryInitBinominalByIndex(diff);
		}
		#endregion ctors

		public string GetBgName()
		{
			StringBuilder ret = new StringBuilder();
			int i = ((int)Stem) - 1;
			ret.Append(stemBgNames[i]); ret.Append(" ");
			i = ((int)Branch) - 1;
			ret.Append(branchBgNames[i]);

			return ret.ToString();
		}

		private string GetBgAbr()
		{
			StringBuilder ret = new StringBuilder();
			
			ret.Append(stemBgAbrs[(int)Stem]);
			ret.Append(" ");
			ret.Append(branchBgAbrs[(int)Branch]);

			return ret.ToString();
		}

		public override string ToString()
		{
			return GetBgName();
		}

		/// <summary>
		/// Get binominal index (between 1 and 60)
		/// </summary>
		/// <param name="diff">The difference between milestone date and current one</param>
		/// <returns>[1 - 60]</returns>
		private int GetSexagesimalIndex(int diff)
		{
			int ret = 0;

			if (diff >= 0)
			{ ret = diff % 60; }
			else
			{
				ret = diff % 60;
				ret = ret + 60;
				ret = ret % 60;
			}

			return ret;
		}
		
		/// <summary>
		/// Generates binominal data according to the 0-based index
		/// </summary>
		/// <param name="index">[0 - 60)</param>
		/// <returns></returns>
		private bool TryInitBinominalByIndex(int index)
		{
			bool ret = false;

			if (index >= 0 && index < 60)
			{
				int st = 1;
				int br = 1;
				for (int i = 0; i < 60; i++)
				{
					if (index == i)
					{
						this.Id = (sbyte)(i + 1);	// 1-based ID
						this.Stem = (Stems)st;
						this.Branch = (Branches)br;
						ret = true;
						break;
					}
					st = (st == 10) ? 1 : st + 1;
					br = (br == 12) ? 1 : br + 1;
				}
			}

			return ret;
		}
	}
}
